package cn.edu.neu.vmmigeval.cloud.policy.impl;


import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;
import cn.edu.neu.vmmigeval.cloud.policy.MigratedHostPolicy;
import cn.edu.neu.vmmigeval.cloud.util.MathUtil;
import cn.edu.neu.vmmigeval.cloud.util.UtilizationHistoryUtil;

public class MigratedHostPolicyMedianAbsoluteDeviation extends MigratedHostPolicy {

	/** The safety parameter. */
	private double safetyParameter = 1500;
	
	/**
	 * Instantiates a new power vm allocation policy migration mad.
	 * 
//	 * @param hostList the host list
	 * @param safetyParameter the safety parameter
	 * @param utilizationThreshold the utilization threshold
	 */
	public MigratedHostPolicyMedianAbsoluteDeviation(
			//List<Host> hostList,
			double safetyParameter,
			double utilizationThreshold) {
		super();
		setSafetyParameter(safetyParameter);
	}
	
	public MigratedHostPolicyMedianAbsoluteDeviation(){
		
	}

	/**
	 * Checks if is host over utilized.
	 * 
	 * @param host the host
	 * @return true, if is host over utilized
	 */
	@Override
	public boolean isHostOverUtilized(Host host) {
		Host _host = host;
		double upperThreshold = 0;
		try {
			upperThreshold = 1 - getSafetyParameter() * getHostUtilizationMad(_host);
			if(upperThreshold<=0.85||upperThreshold>0.99){
				upperThreshold = 0.9;
			}
			//System.out.println(getHostUtilizationMad(_host));
			//System.out.println("is :"+upperThreshold);
		} catch (IllegalArgumentException e) {
			//return getFallbackVmAllocationPolicy().isHostOverUtilized(host);
		}
		//addHistoryEntry(host, upperThreshold);
		double totalRequestedMips = 0;
		for (Vm vm : host.getVmList()) {
			totalRequestedMips += vm.getCurrentCpu();
		}
		double utilization = totalRequestedMips / host.getCurrentCpu();
		return utilization > upperThreshold;
	}

    @Override
    public boolean isHostUnderUtilized(Host host) {
        return false;
    }

    /**
	 * Gets the host utilization mad.
	 * 
	 * @param host the host
	 * @return the host utilization mad
	 */
	protected double getHostUtilizationMad(Host host) throws IllegalArgumentException {
		double[] data = UtilizationHistoryUtil.getUtilizationHistory(host.getUtilizationHistory());
		if (MathUtil.countNonZeroBeginning(data) >= 12) { // 12 has been suggested as a safe value
			return MathUtil.mad(data);
		}
		throw new IllegalArgumentException();
	}

	/**
	 * Sets the safety parameter.
	 * 
	 * @param safetyParameter the new safety parameter
	 */
	protected void setSafetyParameter(double safetyParameter) {
		if (safetyParameter < 0) {
//			Log.printLine("The safety parameter cannot be less than zero. The passed value is: "
//					+ safetyParameter);
			System.exit(0);
		}
		this.safetyParameter = safetyParameter;
	}

	/**
	 * Gets the safety parameter.
	 *
	 * @return the safety parameter
	 */
	protected double getSafetyParameter() {
		return safetyParameter;
	}


}
